home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
intuisup.lha
/
Intuisup
/
source.lha
/
Gadgets
/
gadgets1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-21
|
55KB
|
1,971 lines
/* $Revision Header *** Header built automatically - do not edit! ***********
*
* (C) Copyright 1991 by Torsten Jürgeleit
*
* Name .....: gadgets1.c
* Created ..: Thursday 19-Dec-91 20:52:50
* Revision .: 21
*
* Date Author Comment
* ========= ==================== ====================
* 21-Oct-92 Torsten Jürgeleit corrected autorepeat of arrow
* gadgets under Kick 2.x too
* 14-Sep-92 Torsten Jürgeleit now set_gadget_attributes() with
* data1-3 set to USE_CURRENT_VALUE
* returns current setting
* 12-Sep-92 Torsten Jürgeleit forgot to copy original IntuiMessage
* into ISUP IntuiMessage
* 10-Aug-92 Torsten Jürgeleit perform_gadget_action(): don't use
* lv_SelectedEntry anymore
* 23-Jul-92 Torsten Jürgeleit perform_gadget_action(): report too
* if same palette color entry selected
* again
* 23-Jul-92 Torsten Jürgeleit perform_gadget_action(): only use
* lv_SelectedEntry if GADGET_DATA_-
* FLAG_LISTVIEW_SHOW_SELECTED set
* 20-Jul-92 Torsten Jürgeleit mark end of chained gadgets in
* display_gadgets()
* 19-Jul-92 Torsten Jürgeleit corrected replying of IntuiMessages
* in remove_gadgets()
* 19-Jul-92 Torsten Jürgeleit remove/display_visible_gadget_lists()
* imported from requester/requester.c
* 16-Jul-92 Torsten Jürgeleit size of count gadget changeable
* via modify_gadgets()
* 16-Jul-92 Torsten Jürgeleit lower and upper bound of count
* gadget now changeable via
* set_gadget_attributes()
* 11-Jul-92 Torsten Jürgeleit now RAWKEY instead of VANILLAKEY
* used for gadget hotkeys
* 14-Apr-92 Torsten Jürgeleit if flag GADGET_DATA_FLAG_NO_CLEAR
* set then don't clear area occupied
* by ISUP object before drawing
* 30-Apr-92 Torsten Jürgeleit area gadget occupies now cleared
* before diplaying it
* 28-Apr-92 Torsten Jürgeleit correct disabling in
* set_gadget_attributes() if gadgets
* not displayed -> gl_Window was not
* defined
* 20-Apr-92 Torsten Jürgeleit disable refresh if same entry
* from list view selected
* 01-Apr-92 Torsten Jürgeleit any references to gadget data
* via gl_Data removed
* 01-Apr-92 Torsten Jürgeleit changed parameter size of
* modify_gadget() for new value of
* USE_CURRENT_VALUE (1L << 31)
* 11-Mar-92 Torsten Jürgeleit guru if toggeling DISABLED of NOT
* displayed ISUP object via
* set_gadget_attributes()
* 24-Jan-92 Torsten Jürgeleit new function modify_gadget()
* 28-Dec-91 Torsten Jürgeleit correct highliting of toggle
* select buttons
* 19-Dec-91 Torsten Jürgeleit Created this file!
*
****************************************************************************
*
* Gadget support routines - part 1
*
* $Revision Header ********************************************************/
/* Includes */
#include <exec/types.h>
#include <exec/memory.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#ifdef AZTEC_C
#include <functions.h> /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
#endif
#include <libraries/memwatch.h> /* header file for memory debug link library (Fish 240) - AFTER functions.h */
#include <string.h>
#include "/render/render.h"
#include "/borders/borders.h"
#include "/texts/texts.h"
#include "/language/language.h"
#include "/pointer/pointer.h"
#include "gadgets.h"
#include "imports.h"
/* Defines */
#define CONVERT_BUFFER_SIZE 10L
/* Imports */
IMPORT struct IntuitionBase *IntuitionBase;
/* Static data */
STATIC struct VisibleGadgetLists visible_gadget_lists = {
{ /* struct SignalSemaphore vg_Semaphore */
{ /* struct Node ss_Link */
NULL, NULL, NT_SEMAPHORE, 0, NULL
}, 0,
{ /* struct MinList ss_WaitQueue */
(struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Tail,
NULL,
(struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Head
},
{ /* struct SemaphoreRequest ss_MultipleLink */
{ /* struct MinNode sr_Link */
NULL, NULL
}, NULL
}, NULL, -1
},
{ /* struct MinList vg_MinList */
(struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Tail,
NULL,
(struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Head
}, 0
};
BYTE hotkey_id[] = "_";
/* Create gadget list */
struct GadgetList *
create_gadgets(struct RenderInfo *ri, struct GadgetData *gd,
SHORT hoffset, SHORT voffset, BYTE **language_text_array)
{
USHORT data_entries;
if (ri && ri->ri_ID == ISUP_ID && gd &&
(data_entries = count_gadget_data_entries(gd))) {
struct GadgetList *gl;
ULONG gl_size = sizeof(struct GadgetList) + (data_entries - 1) *
sizeof(struct ExtendedGadget *);
if (gl = AllocMem(gl_size, (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
BYTE *gadget_buffer;
ULONG gadget_buffer_size;
gl->gl_RenderInfo = ri;
gl->gl_DataEntries = data_entries;
gl->gl_LanguageTextArray = language_text_array;
if ((gadget_buffer_size = get_gadget_buffer_size(gl, gd)) &&
(gadget_buffer = AllocMem(gadget_buffer_size,
(LONG)MEMF_PUBLIC | MEMF_CLEAR))) {
BYTE *image_buffer = NULL;
ULONG image_buffer_size;
if (image_buffer_size = get_image_buffer_size(gl, gd)) {
image_buffer = AllocMem(image_buffer_size,
(LONG)MEMF_PUBLIC | MEMF_CHIP);
}
if (!image_buffer_size || image_buffer) {
/* Init gadget list struct */
gl->gl_GadgetBuffer = gadget_buffer;
gl->gl_GadgetBufferSize = gadget_buffer_size;
gl->gl_ImageBuffer = image_buffer;
gl->gl_ImageBufferSize = image_buffer_size;
gl->gl_ID = ISUP_ID;
init_gadgets(gl, gd, hoffset, voffset);
return(gl);
}
FreeMem(gadget_buffer, gadget_buffer_size);
}
FreeMem(gl, gl_size);
}
}
return(NULL);
}
/* Free gadget list */
VOID
free_gadgets(struct GadgetList *gl)
{
if (gl && gl->gl_ID == ISUP_ID) {
USHORT i, data_entries = gl->gl_DataEntries;
if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
remove_gadgets(gl);
}
/* Close fonts */
for (i = 0; i < data_entries; i++) {
struct ExtendedGadget *egad = gl->gl_Gadgets[i];
if (egad->eg_Flags & EXTENDED_GADGET_FLAG_CLOSE_FONT) {
CloseFont(egad->eg_TextFont);
}
}
/* Free buffers */
FreeMem(gl->gl_GadgetBuffer, gl->gl_GadgetBufferSize);
if (gl->gl_ImageBufferSize) {
FreeMem(gl->gl_ImageBuffer, gl->gl_ImageBufferSize);
}
FreeMem(gl, (LONG)(sizeof(struct GadgetList) +
(gl->gl_DataEntries - 1) * sizeof(struct ExtendedGadget *)));
}
}
/* Display gadget list */
VOID
display_gadgets(struct Window *win, struct GadgetList *gl)
{
if (win && gl && gl->gl_ID == ISUP_ID &&
!(gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
struct RenderInfo *ri = gl->gl_RenderInfo;
struct VisibleGadgetLists *vg = &visible_gadget_lists;
struct ExtendedGadget *last_egad;
USHORT i, data_entries = gl->gl_DataEntries,
clear_flags = (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW ?
0 : CLEAR_WINDOW_FLAG_ABSOLUTE_POS);
/* Mark gadget list as displayed */
gl->gl_Window = win;
gl->gl_Flags |= GADGET_LIST_FLAG_DISPLAYED;
/* Increment visible gadget list counter */
ObtainSemaphore(&vg->vg_Semaphore);
AddTail((struct List *)&vg->vg_MinList, (struct Node *)&gl->gl_MinNode);
vg->vg_Count++;
ReleaseSemaphore(&vg->vg_Semaphore);
/* Link gadget list */
for (i = 0, last_egad = NULL; i < data_entries; i++) {
struct ExtendedGadget *egad = gl->gl_Gadgets[i];
/* First clear area occupied by this ISUP object */
if (!(egad->eg_DataFlags & GADGET_DATA_FLAG_NO_CLEAR)) {
clear_window(ri, win, egad->eg_BorderLeftEdge,
egad->eg_BorderTopEdge, egad->eg_BorderWidth,
egad->eg_BorderHeight, clear_flags);
}
/* Move mouse pointer to this ISUP object */
if (egad->eg_DataFlags & GADGET_DATA_FLAG_MOVE_POINTER) {
struct Gadget *gad = &egad->eg_Gadget;
move_mouse_pointer(win, gad->LeftEdge + gad->Width / 2,
gad->TopEdge + gad->Height / 2, FALSE);
}
/* Link gadgets of this ISUP object */
do {
if (last_egad) {
last_egad->eg_Gadget.NextGadget = &egad->eg_Gadget;
}
last_egad = egad;
} while (egad = egad->eg_NextGadget);
}
/* Mark end of gadget list */
if (last_egad) {
last_egad->eg_Gadget.NextGadget = NULL;
}
/* Append new gadgets to window's gadget list and refresh them */
AddGList(win, &gl->gl_Gadgets[0]->eg_Gadget, -1L, -1L, (LONG)NULL);
refresh_gadgets(gl);
}
}
/* Refresh gadget list */
VOID
refresh_gadgets(struct GadgetList *gl)
{
if (gl && gl->gl_ID == ISUP_ID &&
(gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
USHORT i, data_entries = gl->gl_DataEntries;
for (i = 0; i < data_entries; i++) {
refresh_gadget(gl->gl_Gadgets[i]);
}
}
}
/* Modify gadget position and dimension */
VOID
modify_gadget(struct GadgetList *gl, USHORT data_entry, LONG left_edge,
LONG top_edge, ULONG width, ULONG height)
{
if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries &&
(left_edge != USE_CURRENT_VALUE || top_edge != USE_CURRENT_VALUE ||
width != USE_CURRENT_VALUE || height != USE_CURRENT_VALUE)) {
struct ExtendedGadget *egad = gl->gl_Gadgets[data_entry];
VOID *data = egad + 1;
SHORT dx, dy;
/* Clear old gadget */
if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
struct RenderInfo *ri = gl->gl_RenderInfo;
struct RastPort *rp = gl->gl_Window->RPort;
SHORT x, y;
SetAPen(rp, (LONG)ri->ri_BackPen);
SetDrMd(rp, (LONG)JAM1);
/* Clear gadget */
x = egad->eg_BorderLeftEdge;
y = egad->eg_BorderTopEdge;
/* Inner window position needed ? */
if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
x += ri->ri_WindowBorderLeft;
y += ri->ri_WindowBorderTop;
}
RectFill(rp, (LONG)x, (LONG)y, (LONG)(x + egad->eg_BorderWidth - 1),
(LONG)(y + egad->eg_BorderHeight - 1));
/* Clear gadget text - don't forget underscore !!! */
if (egad->eg_Text) {
x = egad->eg_Gadget.LeftEdge + egad->eg_TextLeftEdge;
y = egad->eg_Gadget.TopEdge + egad->eg_TextTopEdge;
RectFill(rp, (LONG)x, (LONG)y, (LONG)(x + egad->eg_TextWidth - 1),
(LONG)(y + egad->eg_TextFont->tf_YSize));
}
}
/* Calc difference to old position */
if (left_edge == USE_CURRENT_VALUE) {
dx = 0;
} else {
dx = left_edge - egad->eg_BorderLeftEdge;
}
if (top_edge == USE_CURRENT_VALUE) {
dy = 0;
} else {
dy = top_edge - egad->eg_BorderTopEdge;
}
/* Move gadget */
if (dx || dy) {
struct ExtendedGadget *eg = egad;
/* Move all extended gadgets belonging to this object */
do {
eg->eg_BorderLeftEdge += dx;
eg->eg_BorderTopEdge += dy;
eg->eg_Gadget.LeftEdge += dx;
eg->eg_Gadget.TopEdge += dy;
} while (eg = eg->eg_NextGadget);
/* Move special gadget data */
switch (egad->eg_Type) {
case EXTENDED_GADGET_TYPE_CYCLE :
((struct CycleData *)data)->cy_LeftEdge += dx;
((struct CycleData *)data)->cy_TopEdge += dy;
break;
case EXTENDED_GADGET_TYPE_COUNT :
((struct CountData *)data)->co_LeftEdge += dx;
((struct CountData *)data)->co_TopEdge += dy;
break;
case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
((struct ListViewData *)data)->lv_LeftEdge += dx;
((struct ListViewData *)data)->lv_TopEdge += dy;
break;
}
}
/* Calc difference to old dimension */
if (width == USE_CURRENT_VALUE) {
dx = 0;
} else {
dx = width - egad->eg_BorderWidth;
}
if (height == USE_CURRENT_VALUE) {
dy = 0;
} else {
dy = height - egad->eg_BorderHeight;
}
/* Resize only some gadgets */
if (dx || dy) {
struct Border *border1 = NULL, *border2 = NULL;
USHORT border1_type, border2_type;
ULONG flags = egad->eg_DataFlags;
BOOL resize = FALSE;
switch (egad->eg_Type) {
case EXTENDED_GADGET_TYPE_BUTTON :
if (!(flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
border1_type = BORDER_DATA_TYPE_BOX1_OUT;
border1 = (struct Border *)
egad->eg_Gadget.GadgetRender;
if (!(flags & GADGET_DATA_FLAG_HIGH_COMP)) {
border2_type = BORDER_DATA_TYPE_BOX1_IN;
border2 = (struct Border *)
egad->eg_Gadget.SelectRender;
}
resize = TRUE;
}
break;
case EXTENDED_GADGET_TYPE_SLIDER_PROP :
border1_type = BORDER_DATA_TYPE_BOX1_OUT;
border1 = (struct Border *)egad->eg_Render;
resize = TRUE;
break;
case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
if (flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS) {
border1_type = BORDER_DATA_TYPE_BOX1_OUT;
border1 = (struct Border *)egad->eg_Render;
resize = TRUE;
}
break;
case EXTENDED_GADGET_TYPE_COUNT :
border1_type = BORDER_DATA_TYPE_BOX1_OUT;
border1 = (struct Border *)egad->eg_Gadget.GadgetRender;
resize = TRUE;
/* Move area for current value */
((struct CountData *)data)->co_LeftEdge =
egad->eg_Gadget.LeftEdge + (egad->eg_Gadget.Width + dx -
((struct CountData *)data)->co_Width) / 2;
((struct CountData *)data)->co_TopEdge =
egad->eg_Gadget.TopEdge + (egad->eg_Gadget.Height + dy -
((struct CountData *)data)->co_Height) / 2;
break;
}
if (resize == TRUE) {
/* Resize gadget */
egad->eg_BorderWidth += dx;
egad->eg_BorderHeight += dy;
egad->eg_Gadget.Width += dx;
egad->eg_Gadget.Height += dy;
/* Resize gadget text */
if (egad->eg_Text) {
/* Change horizontal pos */
if (flags & GADGET_DATA_FLAG_TEXT_RIGHT) {
egad->eg_TextLeftEdge += dx;
} else {
if (!(flags & GADGET_DATA_FLAG_TEXT_LEFT)) {
egad->eg_TextLeftEdge += dx / 2;
}
}
/* Change vertical pos */
if (flags & GADGET_DATA_FLAG_TEXT_BELOW) {
egad->eg_TextTopEdge += dy;
} else {
if (!(flags & GADGET_DATA_FLAG_TEXT_ABOVE)) {
egad->eg_TextTopEdge += dy / 2;
}
}
}
/* Resize border */
if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
if (border1) {
resize_border(border1, egad->eg_BorderWidth,
egad->eg_BorderHeight, border1_type);
}
if (border2) {
resize_border(border2, egad->eg_BorderWidth,
egad->eg_BorderHeight, border2_type);
}
}
}
}
/* Finally refresh modified gadget */
refresh_gadget(egad);
}
}
/* Set gadget attributes */
ULONG
set_gadget_attributes(struct GadgetList *gl, USHORT data_entry,
ULONG flag_mask, ULONG flag_bits, ULONG data1, ULONG data2, VOID *data3)
{
ULONG value = 0;
if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries) {
struct ExtendedGadget *egad = gl->gl_Gadgets[data_entry];
struct Gadget *gad = &egad->eg_Gadget;
USHORT type = egad->eg_DataType;
ULONG flags = egad->eg_DataFlags;
BOOL refresh = FALSE;
/* Change gadget data flags */
if (flag_mask) {
ULONG mask;
USHORT i;
/* Change gadget data flags according to flag mask */
for (i = 0, mask = 1; i < MAX_DATA_FLAG_BITS; i++, mask <<= 1) {
/* Check if flag bit set */
if (flag_mask & mask) {
BOOL change = FALSE;
/* Change flag only if changeable and valid for gadget type */
switch (mask) {
case GADGET_DATA_FLAG_DISABLED :
/* Toggle able state of gadget */
if ((flags & mask) != (flag_bits & mask)) {
struct RastPort *rp; /* init later !!! */
struct ExtendedGadget *temp_egad = egad;
UBYTE displayed = gl->gl_Flags &
GADGET_LIST_FLAG_DISPLAYED;
/* Set draw mode and color for clearing enabled select box */
if (displayed &&
(flags & GADGET_DATA_FLAG_DISABLED)) {
rp = gl->gl_Window->RPort; /* ONLY if displayed then gl_Window is valid !!!*/
SetDrMd(rp, (LONG)JAM1);
SetAPen(rp, (LONG)gl->gl_RenderInfo->ri_BackPen);
}
/* Toggle able state of ALL gadgets belonging to ISUP object */
do {
struct Gadget *temp_gad = &temp_egad->eg_Gadget;
if (flags & GADGET_DATA_FLAG_DISABLED) {
temp_gad->Flags &= ~GADGDISABLED;
/* Clear ghosted gadget select box */
if (displayed) {
RectFill(rp, (LONG)temp_gad->LeftEdge,
(LONG)temp_gad->TopEdge,
(LONG)(temp_gad->LeftEdge +
temp_gad->Width - 1),
(LONG)(temp_gad->TopEdge +
temp_gad->Height - 1));
}
} else {
temp_gad->Flags |= GADGDISABLED;
}
} while (temp_egad = temp_egad->eg_NextGadget);
/* Refresh gadget before leaving function */
refresh = TRUE;
change = TRUE;
}
break;
case GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE :
if (type == GADGET_DATA_TYPE_STRING ||
type == GADGET_DATA_TYPE_INTEGER) {
change = TRUE;
}
break;
case GADGET_DATA_FLAG_STRING_UNSIGNED_DEC :
if (type == GADGET_DATA_TYPE_STRING) {
change = TRUE;
}
break;
case GADGET_DATA_FLAG_STRING_SIGNED_DEC :
if (type == GADGET_DATA_TYPE_STRING) {
change = TRUE;
}
break;
case GADGET_DATA_FLAG_STRING_HEX :
if (type == GADGET_DATA_TYPE_STRING) {
change = TRUE;
}
break;
case GADGET_DATA_FLAG_STRING_BIN :
if (type == GADGET_DATA_TYPE_STRING) {
change = TRUE;
}
break;
case GADGET_DATA_FLAG_MOVE_POINTER :
change = TRUE;
break;
}
/* Change flag bit if neccessary */
if (change == TRUE) {
flags &= ~mask;
flags |= flag_bits & mask;
}
}
}
/* Save changed gadget data flags */
egad->eg_DataFlags = flags;
}
/* Get current setting and change special gadget data */
switch (type) {
case GADGET_DATA_TYPE_BUTTON :
if (gad->Activation & TOGGLESELECT) {
if (gad->Flags & SELECTED) {
value = 1;
}
if (data1 != USE_CURRENT_VALUE) {
if (data1) {
gad->Flags |= SELECTED;
} else {
if (gad->Flags & SELECTED) {
/* Prepare gadget state manually (unselected) */
change_gadget(egad);
}
gad->Flags &= ~SELECTED;
}
change_gadget(egad);
}
}
break;
case GADGET_DATA_TYPE_CHECK :
if (gad->Flags & SELECTED) {
value = 1;
}
if (data1 != USE_CURRENT_VALUE) {
if (data1) {
gad->Flags |= SELECTED;
} else {
gad->Flags &= ~SELECTED;
}
change_gadget(egad);
}
break;
case GADGET_DATA_TYPE_MX :
{
struct MXData *mx = (VOID *)(egad + 1);
value = mx->mx_ActiveEntry;
if (data2 != USE_CURRENT_VALUE) {
ULONG entries = mx->mx_TextEntries, active = data2;
if (active >= entries) {
active = entries - 1; /* activate last entry */
}
mx->mx_ActiveEntry = active;
change_gadget(egad);
}
}
break;
case GADGET_DATA_TYPE_STRING :
case GADGET_DATA_TYPE_INTEGER :
{
struct StringInfo *sinfo = (struct StringInfo *)
gad->SpecialInfo;
BYTE *buffer = (BYTE *)sinfo->Buffer;
if (type == GADGET_DATA_TYPE_STRING) {
value = (ULONG)buffer;
} else {
value = sinfo->LongInt;
}
if ((ULONG)data3 != USE_CURRENT_VALUE) {
BYTE *input = data3;
ULONG len, max_len = sinfo->MaxChars;
if (type == GADGET_DATA_TYPE_STRING) {
/* Convert number for string input gadget */
if (flags & GADGET_DATA_FLAG_STRING_UNSIGNED_DEC) {
if ((LONG)input != -1L) {
len = convert_unsigned_dec((ULONG)input,
buffer, DEC_NUM_CONVERT_FLAGS);
} else {
len = 0;
}
} else {
if (flags & GADGET_DATA_FLAG_STRING_SIGNED_DEC) {
if ((LONG)input != -1L) {
len = convert_signed_dec((ULONG)input, buffer,
DEC_NUM_CONVERT_FLAGS);
} else {
len = 0;
}
} else {
if (flags & GADGET_DATA_FLAG_STRING_HEX) {
if ((LONG)input != -1L) {
len = convert_hex((ULONG)input, buffer,
HEX_NUM_CONVERT_FLAGS);
} else {
len = 0;
}
} else {
if (flags & GADGET_DATA_FLAG_STRING_BIN) {
if ((LONG)input != -1L) {
len = convert_bin((ULONG)input, buffer,
BIN_NUM_CONVERT_FLAGS);
} else {
len = 0;
}
} else {
if (input) {
if ((len = strlen(input)) > max_len) {
len = max_len;
}
strncpy(buffer, input, (size_t)len);
} else {
len = 0;
}
}
}
}
}
} else {
/* Convert number for integer input gadget */
if ((LONG)input != -1L) {
len = convert_unsigned_dec((ULONG)input, buffer, 0);
} else {
len = 0;
}
}
*(buffer + len) = '\0'; /* mark end of string */
sinfo->BufferPos = 0;
change_gadget(egad);
}
}
break;
case GADGET_DATA_TYPE_SLIDER :
{
struct SliderData *sl = (VOID *)(egad + 1);
value = sl->sl_Level;
if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE
|| (ULONG)data3 != USE_CURRENT_VALUE) {
ULONG min, max, level;
if (data1 != USE_CURRENT_VALUE) {
min = sl->sl_Min = data1;
} else {
min = sl->sl_Min;
}
if (data2 != USE_CURRENT_VALUE) {
max = sl->sl_Max = data2;
} else {
max = sl->sl_Max;
}
if ((ULONG)data3 != USE_CURRENT_VALUE) {
level = (ULONG)data3;
} else {
level = sl->sl_Level;
}
if ((LONG)level < (LONG)min) {
level = min;
} else {
if ((LONG)level > (LONG)max) {
level = max;
}
}
sl->sl_Level = level;
change_gadget(egad);
}
}
break;
case GADGET_DATA_TYPE_SCROLLER :
{
struct ScrollerData *sc = (VOID *)(egad + 1);
value = sc->sc_Top;
if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE
|| (ULONG)data3 != USE_CURRENT_VALUE) {
ULONG visible, total, top;
if (data1 != USE_CURRENT_VALUE) {
visible = sc->sc_Visible = data1;
} else {
visible = sc->sc_Visible;
}
if (data2 != USE_CURRENT_VALUE) {
total = sc->sc_Total = data2;
} else {
total = sc->sc_Total;
}
if ((ULONG)data3 != USE_CURRENT_VALUE) {
top = (ULONG)data3;
} else {
top = sc->sc_Top;
}
if (top >= total || (total - top) < visible) {
top = (total > visible ? total - visible :
visible - total);
}
sc->sc_Top = top;
change_gadget(egad);
}
}
break;
case GADGET_DATA_TYPE_CYCLE :
{
struct CycleData *cy = (VOID *)(egad + 1);
value = cy->cy_ActiveEntry;
if (data2 != USE_CURRENT_VALUE) {
ULONG entries = cy->cy_TextEntries, active = data2;
if (active > entries) {
active = entries; /* activate last entry */
}
cy->cy_ActiveEntry = active;
change_gadget(egad);
}
}
break;
case GADGET_DATA_TYPE_COUNT :
{
struct CountData *co = (VOID *)(egad + 1);
value = co->co_Value;
if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE
|| (ULONG)data3 != USE_CURRENT_VALUE) {
if ((ULONG)data1 != USE_CURRENT_VALUE ||
(ULONG)data2 != USE_CURRENT_VALUE) {
struct IntuiText itext;
USHORT min_len, max_len, width;
SHORT left_edge;
ULONG min, max;
/* Calc new left edge and width of area for count value */
if ((ULONG)data1 != USE_CURRENT_VALUE) {
min = (ULONG)data1;
} else {
min = co->co_Min;
}
if ((ULONG)data2 != USE_CURRENT_VALUE) {
max = (ULONG)data2;
} else {
max = co->co_Max;
}
if (flags & GADGET_DATA_FLAG_COUNT_SIGNED_DEC) {
min_len = convert_signed_dec((LONG)min,
(BYTE *)NULL, 0);
max_len = convert_signed_dec((LONG)max,
(BYTE *)NULL, 0);
} else {
min_len = convert_unsigned_dec(min, (BYTE *)NULL, 0);
max_len = convert_unsigned_dec(max, (BYTE *)NULL, 0);
}
itext.ITextFont = egad->eg_TextAttr;
itext.IText = (UBYTE *)"8";
width = IntuiTextLength(&itext) *
(min_len > max_len ? min_len : max_len);
left_edge = gad->LeftEdge +
(SHORT)(gad->Width - width) / 2;
/* Clear old area */
if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
print_count_text(egad, FALSE);
}
/* Change count data */
co->co_LeftEdge = left_edge;
co->co_Width = width;
co->co_Min = min;
co->co_Max = max;
/* Now let's compare current value with new bounds */
if ((ULONG)data3 == USE_CURRENT_VALUE) {
data3 = (VOID *)co->co_Value;
}
}
if ((ULONG)data3 != USE_CURRENT_VALUE) {
ULONG min = co->co_Min, max = co->co_Max,
num = (ULONG)data3;
/* Compare new current value with bounds */
if ((LONG)num < (LONG)min) {
num = min;
} else {
if ((LONG)num > (LONG)max) {
num = max;
}
}
co->co_Value = num;
change_gadget(egad);
}
}
}
break;
case GADGET_DATA_TYPE_LISTVIEW :
{
struct ListViewData *lv = (VOID *)(egad + 1);
if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
value = lv->lv_SelectedEntry;
} else {
value = lv->lv_TopEntry;
}
if (data2 != USE_CURRENT_VALUE ||
(ULONG)data3 != USE_CURRENT_VALUE) {
ULONG visible, entries, top;
if ((ULONG)data3 != USE_CURRENT_VALUE) {
struct List *list = data3;
struct Node *node;
/* Count list nodes */
entries = 0;
if (list) {
node = list->lh_Head;
while (node = node->ln_Succ) {
entries++;
}
}
lv->lv_List = list;
lv->lv_ListEntries = entries;
}
if (data2 != USE_CURRENT_VALUE ||
(ULONG)data3 != USE_CURRENT_VALUE) {
struct List *list = data3;
struct Node *node;
ULONG sel;
list = lv->lv_List;
visible = lv->lv_VisibleEntries;
entries = lv->lv_ListEntries;
/* Search top list node */
if (!entries) {
sel = 0;
top = 0;
node = NULL;
} else {
if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
/* Calc correct top entry for selected entry */
if (data2 != USE_CURRENT_VALUE) {
sel = data2;
} else {
sel = lv->lv_SelectedEntry;
}
if (sel >= entries) {
sel = entries - 1;
}
if (sel && entries > visible) {
if (sel > (entries - visible)) {
ULONG i;
top = entries - visible;
node = list->lh_TailPred;
for (i = entries - top - 1; i; i--) {
node = node->ln_Pred;
}
} else {
node = list->lh_Head;
if (sel > (visible >> 1)) {
ULONG i;
top = sel - (visible >> 1);
for (i = 0; i < top; i++) {
node = node->ln_Succ;
}
} else {
top = 0;
}
}
} else {
top = 0;
node = list->lh_Head;
}
} else {
/* Calc top entry ignoring selected entry */
if (data2 != USE_CURRENT_VALUE) {
top = data2;
} else {
top = lv->lv_TopEntry;
}
if (top && entries > visible) {
if (top > entries ||
(entries - top) < visible) {
ULONG i;
top = entries - visible;
node = list->lh_TailPred;
for (i = entries - top - 1; i; i--) {
node = node->ln_Pred;
}
} else {
ULONG i;
node = list->lh_Head;
for (i = 0; i < top; i++) {
node = node->ln_Succ;
}
}
} else {
top = 0;
node = list->lh_Head;
}
sel = top;
}
}
/* Init list view data */
lv->lv_TopNode = node;
lv->lv_TopEntry = top;
lv->lv_SelectedEntry = sel;
change_gadget(egad); /* before changing list entry gadget flags !!! */
/* Set GADGHNONE flag for all entry gadgets without list node */
if (!(flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY)) {
struct ExtendedGadget *temp_egad;
USHORT i;
/* Get ptr to first entry gadget */
temp_egad = egad->eg_NextGadget->eg_NextGadget->
eg_NextGadget;
for (i = 0; i < visible; i++, top++) {
struct Gadget *temp_gad = &temp_egad->eg_Gadget;
if (top < entries) {
temp_gad->Flags = (temp_gad->Flags &
~GADGHIGHBITS) | GADGHCOMP;
} else {
temp_gad->Flags = (temp_gad->Flags &
~GADGHIGHBITS) | GADGHNONE;
}
temp_egad = temp_egad->eg_NextGadget;
}
}
}
}
}
break;
case GADGET_DATA_TYPE_PALETTE :
{
struct PaletteData *pd = (VOID *)(egad + 1);
value = pd->pd_ActiveColor;
if ((ULONG)data3 != USE_CURRENT_VALUE) {
ULONG offset = pd->pd_ColorOffset, max = pd->pd_MaxColors,
active = (ULONG)data3;
if (active < offset) {
active = offset;
} else {
if (active >= (max + offset)) {
active = max + offset - 1;
}
}
pd->pd_ActiveColor = active;
change_gadget(egad);
}
}
break;
}
/* Finally refresh gadget if necessary */
if (refresh == TRUE) {
refresh_gadget(egad);
}
}
return(value);
}
/* Activate string or integer input gadget */
VOID
activate_input_gadget(struct GadgetList *gl, USHORT data_entry)
{
if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries &&
(gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
struct ExtendedGadget *egad = gl->gl_Gadgets[data_entry];
USHORT type = egad->eg_DataType;
if (type == GADGET_DATA_TYPE_STRING ||
type == GADGET_DATA_TYPE_INTEGER) {
struct Gadget *gad = &egad->eg_Gadget;
/* If selected input gadget disabled then activate next one */
if (gad->Flags & GADGDISABLED) {
if (egad->eg_DataFlags & GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE) {
struct InputData *id = (struct InputData *)(egad + 1);
/* !!! Recurrence (in german: Rekursion) !!! */
activate_input_gadget(gl, id->id_ActivateNext);
}
} else {
struct Window *win = gl->gl_Window;
/* First bring screen + window to front */
if (IntuitionBase->ActiveScreen != win->WScreen) {
ScreenToFront(win->WScreen);
}
/* Now activate window + input gadget */
if (IntuitionBase->ActiveWindow != win) {
WindowToFront(win);
ActivateWindow(win);
timer_delay(0L, 500000L);
}
ActivateGadget(gad, win, (LONG)NULL);
}
}
}
}
/* Return gadget address */
struct Gadget *
gadget_address(struct GadgetList *gl, USHORT data_entry)
{
struct Gadget *gad = NULL;
if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries) {
gad = &gl->gl_Gadgets[data_entry]->eg_Gadget;
}
return(gad);
}
/* Remove gadget list from display */
struct Window *
remove_gadgets(struct GadgetList *gl)
{
struct Window *win = NULL;
if (gl && gl->gl_ID == ISUP_ID &&
(gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
struct VisibleGadgetLists *vg = &visible_gadget_lists;
struct IntuiMessage *succ, *msg;
USHORT i, data_entries = gl->gl_DataEntries;
/* Mark gadget list as not displayed */
win = gl->gl_Window;
gl->gl_Window = NULL;
gl->gl_Flags &= ~GADGET_LIST_FLAG_DISPLAYED;
/* Decrement visible gadget list counter */
ObtainSemaphore(&vg->vg_Semaphore);
Remove((struct Node *)&gl->gl_MinNode);
vg->vg_Count--;
ReleaseSemaphore(&vg->vg_Semaphore);
/* Remove gadgets from windows gadget list */
for (i = 0; i < data_entries; i++) {
struct ExtendedGadget *egad = gl->gl_Gadgets[i];
do {
RemoveGList(win, &egad->eg_Gadget, 1L);
} while (egad = egad->eg_NextGadget);
}
/* Reply all ISUP intuition messages belonging to this window */
Forbid();
msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
while (succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ) {
if (msg->IDCMPWindow == win) {
switch (msg->Class) {
case GADGETDOWN :
case GADGETUP :
case MOUSEMOVE :
case INTUITICKS :
case VANILLAKEY : /* for compatibility to < v4.2 only */
case RAWKEY :
Remove((struct Node *)msg);
ReplyMsg((struct Message *)msg);
break;
}
}
msg = succ;
}
Permit();
}
return(win);
}
/* Get intuition msg and perform any action to isup gadgets */
struct IntuiMessage *
get_msg(struct MsgPort *uport)
{
struct IntuiMessage *imsg = NULL;
if (uport) {
struct IntuiMessage *real_imsg;
while (imsg == NULL && (real_imsg = (struct IntuiMessage *)
GetMsg(uport))) {
struct ExtendedGadget *egad;
switch (real_imsg->Class) {
case GADGETDOWN :
egad = (struct ExtendedGadget *)real_imsg->IAddress;
if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
USHORT activation = egad->eg_Gadget.Activation;
/* Perform gadget action and check activation flags */
imsg = perform_gadget_action(egad, real_imsg);
if ((activation & FOLLOWMOUSE) ||
(activation & (GADGIMMEDIATE | RELVERIFY)) ==
(GADGIMMEDIATE | RELVERIFY)) {
struct GadgetList *gl = egad->eg_GadgetList;
/* Save active gadget and set auto repeat delay counter */
gl->gl_ActiveGadget = egad;
gl->gl_AutoRepeatDelay = ARROW_AUTO_REPEAT_START_DELAY;
}
} else {
egad = NULL; /* return imsg later */
}
break;
case GADGETUP :
egad = (struct ExtendedGadget *)real_imsg->IAddress;
if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
imsg = perform_gadget_action(egad, real_imsg);
/* Reset saved active gadget */
egad->eg_GadgetList->gl_ActiveGadget = NULL;
} else {
egad = NULL; /* return imsg later */
}
break;
case MOUSEMOVE :
if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
imsg = perform_gadget_action(egad, real_imsg);
}
break;
case INTUITICKS :
if ((egad = get_active_gadget(real_imsg->IDCMPWindow))
&& (egad->eg_Gadget.Flags & SELECTED)) {
if ((egad->eg_Gadget.Activation & (GADGIMMEDIATE |
RELVERIFY)) == (GADGIMMEDIATE | RELVERIFY)) {
struct GadgetList *gl = egad->eg_GadgetList;
/* Check and decrement auto repeat delay counter */
if (gl->gl_AutoRepeatDelay) {
gl->gl_AutoRepeatDelay--;
} else {
imsg = perform_gadget_action(egad, real_imsg);
}
}
}
break;
case VANILLAKEY : /* for compatibility to < v4.3 only */
if (egad = get_hotkey_gadget(real_imsg->IDCMPWindow,
real_imsg->Code)) {
if (!(egad->eg_Gadget.Flags & GADGDISABLED)) {
imsg = perform_hotkey_action(egad, real_imsg);
}
}
break;
case RAWKEY :
if (egad = get_hotkey_gadget(real_imsg->IDCMPWindow,
convert_rawkey_to_ascii(real_imsg))) {
if (!(egad->eg_Gadget.Flags & GADGDISABLED)) {
imsg = perform_hotkey_action(egad, real_imsg);
}
}
break;
default :
if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
egad->eg_GadgetList->gl_ActiveGadget = NULL;
egad = NULL; /* return imsg later */
}
break;
}
if (!imsg) {
/* If isup msg then reply it, else return it */
if (egad) {
ReplyMsg((struct Message *)real_imsg);
} else {
imsg = real_imsg;
}
}
}
}
return(imsg);
}
/* Reply intuition message and free ISUP message if any */
VOID
reply_msg(struct IntuiMessage *imsg)
{
if (imsg) {
if (imsg->Class == ISUP_ID) {
struct IntuiMessage *real_imsg = *(struct IntuiMessage **)
(imsg + 1);
/* Free ISUP msg */
FreeMem(imsg, (LONG)(sizeof(struct IntuiMessage) +
sizeof(struct IntuiMessage *)));
/* Return real intui msg (ptr direct after ISUP msg) */
imsg = real_imsg;
}
ReplyMsg((struct Message *)imsg);
}
}
/* Perform ISUP gadget action */
STATIC struct IntuiMessage *
perform_gadget_action(struct ExtendedGadget *egad,
struct IntuiMessage *real_imsg)
{
struct IntuiMessage *imsg = NULL;
struct Gadget *gad = &egad->eg_Gadget;
struct GadgetList *gl = egad->eg_GadgetList;
USHORT data_entry = egad->eg_DataEntry;
struct ExtendedGadget *real_egad = gl->gl_Gadgets[data_entry];
struct MXData *mx;
struct ListViewData *lv;
struct PaletteData *pd;
VOID *data = (VOID *)(real_egad + 1);
USHORT type = egad->eg_Type;
ULONG min, max, num, flags = real_egad->eg_DataFlags, value = 0,
class = real_imsg->Class, qualifier = real_imsg->Qualifier;
switch (type) {
case EXTENDED_GADGET_TYPE_BUTTON :
if ((flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) &&
(gad->Flags & SELECTED)) {
/* Prepare gadget state manually (selected) */
change_gadget(real_egad);
value = 1;
}
change_gadget(real_egad);
break;
case EXTENDED_GADGET_TYPE_CHECK :
if (gad->Flags & SELECTED) {
value = 1;
}
break;
case EXTENDED_GADGET_TYPE_MX :
mx = data;
if (mx->mx_ActiveEntry != egad->eg_Gadget.GadgetID) {
mx->mx_ActiveEntry = value = egad->eg_Gadget.GadgetID;
} else {
real_imsg = NULL;
}
change_gadget(real_egad);
break;
case EXTENDED_GADGET_TYPE_STRING :
case EXTENDED_GADGET_TYPE_INTEGER :
if (!(qualifier & QUALIFIER_ALT) &&
(flags & GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE)) {
struct InputData *id = data;
USHORT next_input;
if (qualifier & QUALIFIER_SHIFT) {
next_input = id->id_ActivatePrev;
} else {
next_input = id->id_ActivateNext;
}
activate_input_gadget(gl, next_input);
}
if (type == EXTENDED_GADGET_TYPE_STRING) {
value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->Buffer;
} else {
value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->LongInt;
}
break;
case EXTENDED_GADGET_TYPE_SLIDER_PROP :
if (class == GADGETUP) {
change_gadget(real_egad);
real_imsg = NULL;
} else {
struct SliderData *sl = data;
struct PropInfo *pi = (struct PropInfo *)gad->SpecialInfo;
min = sl->sl_Min;
max = (LONG)sl->sl_Max - (LONG)min;
if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
num = max - ((LONG)get_prop_pos(max + 1, 1L, pi->VertPot) -
(LONG)min);
} else {
num = (LONG)get_prop_pos(max + 1, 1L, pi->HorizPot) +
(LONG)min;
}
if (sl->sl_Level != num) {
sl->sl_Level = value = num;
} else {
real_imsg = NULL;
}
}
break;
case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
if (class == GADGETUP) {
change_gadget(real_egad);
real_imsg = NULL;
} else {
struct ScrollerData *sc = data;
struct PropInfo *pi = (struct PropInfo *)gad->SpecialInfo;
min = sc->sc_Visible;
max = sc->sc_Total;
if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
num = get_prop_pos(max, min, pi->VertPot);
} else {
num = get_prop_pos(max, min, pi->HorizPot);
}
if (sc->sc_Top != num) {
sc->sc_Top = value = num;
} else {
real_imsg = NULL;
}
}
break;
case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
if (class == GADGETUP) {
real_imsg = NULL;
} else {
struct ScrollerData *sc = data;
num = sc->sc_Top;
if (num > 0) {
sc->sc_Top = value = num - 1;
change_gadget(real_egad);
} else {
real_imsg = NULL;
}
}
break;
case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
case EXTENDED_GADGET_TYPE_SCROLLER_UP :
if (class == GADGETUP) {
real_imsg = NULL;
} else {
struct ScrollerData *sc = data;
num = sc->sc_Top;
min = sc->sc_Visible;
max = sc->sc_Total;
num++;
if (num < max && (max - num) >= min) {
sc->sc_Top = value = num;
change_gadget(real_egad);
} else {
real_imsg = NULL;
}
}
break;
case EXTENDED_GADGET_TYPE_CYCLE :
if (change_cycle_gadget(real_egad, qualifier) == TRUE) {
value = ((struct CycleData *)data)->cy_ActiveEntry;
} else {
real_imsg = NULL;
}
break;
case EXTENDED_GADGET_TYPE_COUNT :
change_count_gadget(real_egad);
value = ((struct CountData *)data)->co_Value;
break;
case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
if (class == GADGETUP) {
change_gadget(real_egad);
} else {
lv = data;
min = lv->lv_VisibleEntries;
max = lv->lv_ListEntries;
num = get_prop_pos(max, min, ((struct PropInfo *)
gad->SpecialInfo)->VertPot);
if ((min = lv->lv_TopEntry) != num) {
struct Node *node = lv->lv_TopNode;
USHORT i;
if (min > num) {
for (i = min - num; i > 0; i--) {
node = node->ln_Pred;
}
} else {
for (i = num - min; i > 0; i--) {
node = node->ln_Succ;
}
}
lv->lv_TopNode = node;
lv->lv_TopEntry = num;
if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
print_list_view_text(egad);
}
}
}
real_imsg = NULL;
break;
case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
if (class != GADGETUP) {
lv = data;
num = lv->lv_TopEntry;
if (num > 0) {
lv->lv_TopNode = lv->lv_TopNode->ln_Pred;
lv->lv_TopEntry = value = num - 1;
change_gadget(real_egad);
}
}
real_imsg = NULL;
break;
case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
if (class != GADGETUP) {
lv = data;
min = lv->lv_VisibleEntries;
max = lv->lv_ListEntries;
num = lv->lv_TopEntry + 1;
if (num < max && (max - num) >= min) {
lv->lv_TopNode = lv->lv_TopNode->ln_Succ;
lv->lv_TopEntry = value = num;
change_gadget(real_egad);
}
}
real_imsg = NULL;
break;
case EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY :
lv = data;
max = lv->lv_ListEntries;
num = lv->lv_TopEntry + egad->eg_Gadget.GadgetID;
if (num < max) {
lv->lv_SelectedEntry = value = num;
if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
change_gadget(real_egad);
}
} else {
real_imsg = NULL;
}
break;
case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
real_imsg = NULL;
break;
case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
pd = data;
pd->pd_ActiveColor = value = egad->eg_Gadget.GadgetID;
change_gadget(real_egad);
break;
}
if (real_imsg) {
imsg = create_intui_message(real_imsg, gl, data_entry, value);
}
return(imsg);
}
/* Perform hotkey gadget action */
STATIC struct IntuiMessage *
perform_hotkey_action(struct ExtendedGadget *egad,
struct IntuiMessage *real_imsg)
{
struct IntuiMessage *imsg = NULL;
struct Gadget *gad = &egad->eg_Gadget;
struct GadgetList *gl = egad->eg_GadgetList;
struct Window *win = gl->gl_Window;
struct RastPort *rp = win->RPort;
USHORT data_entry = egad->eg_DataEntry;
struct ExtendedGadget *real_egad = gl->gl_Gadgets[data_entry];
struct MXData *mx;
struct SliderData *sl;
struct ScrollerData *sc;
struct CycleData *cy;
struct CountData *co;
struct ListViewData *lv;
struct PaletteData *pd;
VOID *data = (VOID *)(real_egad + 1);
ULONG min, max, num, flags = real_egad->eg_DataFlags, value = 0,
qualifier = real_imsg->Qualifier & QUALIFIER_SHIFT;
switch (egad->eg_Type) {
case EXTENDED_GADGET_TYPE_BUTTON :
if (flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) {
if (gad->Flags & SELECTED) {
/* Prepare gadget state manually (selected) */
change_gadget(real_egad);
gad->Flags &= ~SELECTED;
} else {
gad->Flags |= SELECTED;
value = 1;
}
} else {
if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
gad->Flags |= SELECTED;
change_gadget(real_egad);
timer_delay(0L, 100000L);
/* Prepare gadget state manually (unselected) */
change_gadget(real_egad);
gad->Flags &= ~SELECTED;
}
}
change_gadget(real_egad);
break;
case EXTENDED_GADGET_TYPE_CHECK :
if (gad->Flags & SELECTED) {
gad->Flags &= ~SELECTED;
} else {
gad->Flags |= SELECTED;
value = 1;
}
change_gadget(real_egad);
break;
case EXTENDED_GADGET_TYPE_MX :
mx = data;
max = mx->mx_TextEntries;
num = mx->mx_ActiveEntry;
if (qualifier) {
if (num > 0) {
num--;
} else {
num = max - 1;
}
} else {
if (num < (max - 1)) {
num++;
} else {
num = 0;
}
}
mx->mx_ActiveEntry = value = num;
change_gadget(real_egad);
break;
case EXTENDED_GADGET_TYPE_STRING :
case EXTENDED_GADGET_TYPE_INTEGER :
activate_input_gadget(gl, data_entry);
real_imsg = NULL;
break;
case EXTENDED_GADGET_TYPE_SLIDER_PROP :
sl = data;
min = sl->sl_Min;
max = sl->sl_Max;
num = sl->sl_Level;
if (qualifier) {
if ((LONG)num > (LONG)min) {
num--;
} else {
real_imsg = NULL;
}
} else {
if ((LONG)num < (LONG)max) {
num++;
} else {
real_imsg = NULL;
}
}
if (real_imsg) {
sl->sl_Level = value = num;
change_gadget(real_egad);
}
break;
case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
sc = data;
min = sc->sc_Visible;
max = sc->sc_Total;
num = sc->sc_Top;
if (qualifier) {
if (num > 0) {
num--;
} else {
real_imsg = NULL;
}
} else {
if (num < (max - min)) {
num++;
} else {
real_imsg = NULL;
}
}
if (real_imsg) {
sc->sc_Top = value = num;
change_gadget(real_egad);
}
break;
case EXTENDED_GADGET_TYPE_CYCLE :
cy = data;
max = cy->cy_TextEntries;
num = cy->cy_ActiveEntry;
if (qualifier) {
if (num > 0) {
num--;
} else {
num = max - 1;
}
} else {
if (num < (max - 1)) {
num++;
} else {
num = 0;
}
}
if (cy->cy_ActiveEntry != num) {
cy->cy_ActiveEntry = value = num;
change_gadget(real_egad);
} else {
real_imsg = NULL;
}
break;
case EXTENDED_GADGET_TYPE_COUNT :
co = data;
min = co->co_Min;
max = co->co_Max;
num = co->co_Value;
if (qualifier) {
if ((LONG)num > (LONG)min) {
num--;
} else {
real_imsg = NULL;
}
} else {
if ((LONG)num < (LONG)max) {
num++;
} else {
real_imsg = NULL;
}
}
if (real_imsg) {
co->co_Value = value = num;
change_gadget(real_egad);
}
break;
case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
lv = data;
min = lv->lv_VisibleEntries;
max = lv->lv_ListEntries;
if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
num = lv->lv_SelectedEntry;
} else {
num = lv->lv_TopEntry;
}
if (qualifier) {
if (num > 0) {
num--;
} else {
real_imsg = NULL;
}
} else {
if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
if (++num >= max) {
real_imsg = NULL;
}
} else {
if (++num >= max || (max - num) < min) {
real_imsg = NULL;
}
}
}
if (real_imsg) {
set_gadget_attributes(gl, data_entry, 0L, 0L, USE_CURRENT_VALUE,
num, (VOID *)USE_CURRENT_VALUE);
if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
value = lv->lv_SelectedEntry;
} else {
real_imsg = NULL;
}
}
break;
case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
pd = data;
min = pd->pd_ColorOffset;
max = pd->pd_MaxColors;
num = pd->pd_ActiveColor;
if (qualifier) {
if ((LONG)num > (LONG)min) {
num--;
} else {
num = min + max - 1;
}
} else {
if ((LONG)num < (LONG)(min + max - 1)) {
num++;
} else {
num = min;
}
}
pd->pd_ActiveColor = value = num;
change_gadget(real_egad);
break;
}
if (real_imsg) {
imsg = create_intui_message(real_imsg, gl, data_entry, value);
}
return(imsg);
}
/* Create special ISUP intui message */
STATIC struct IntuiMessage *
create_intui_message(struct IntuiMessage *real_imsg, struct GadgetList *gl,
USHORT data_entry, ULONG value)
{
struct IntuiMessage *imsg = NULL;
if (!(imsg = AllocMem((LONG)(sizeof(struct IntuiMessage) +
sizeof(struct IntuiMessage *)), MEMF_PUBLIC))) {
imsg = real_imsg;
} else {
/* Init ISUP intui message */
CopyMem((BYTE *)real_imsg, (BYTE *)imsg, sizeof(struct IntuiMessage));
imsg->Class = ISUP_ID;
imsg->Code = data_entry;
imsg->IAddress = (APTR)value;
imsg->SpecialLink = (struct IntuiMessage *)gl;
/* Put real IntuiMessage ptr direct after ISUP intuition message */
*(struct IntuiMessage **)(imsg + 1) = real_imsg;
}
return(imsg);
}
/* Get active gadget for given window */
STATIC struct ExtendedGadget *
get_active_gadget(struct Window *win)
{
struct VisibleGadgetLists *vg = &visible_gadget_lists;
struct ExtendedGadget *egad = NULL;
USHORT count;
ObtainSemaphore(&vg->vg_Semaphore);
if (count = vg->vg_Count) {
struct GadgetList *gl = (struct GadgetList *)vg->vg_MinList.mlh_Head;
USHORT i;
for (i = 0; i < count; i++) {
if (gl->gl_Window == win && gl->gl_ActiveGadget) {
egad = gl->gl_ActiveGadget;
break;
}
gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
}
}
ReleaseSemaphore(&vg->vg_Semaphore);
return(egad);
}
/* Get hotkey gadget for given window */
STATIC struct ExtendedGadget *
get_hotkey_gadget(struct Window *win, USHORT hotkey)
{
struct ExtendedGadget *result_egad = NULL;
/* First check for valid hotkey (printable character) */
hotkey = tolower(hotkey);
if (hotkey >= ' ' && hotkey <= '~') {
struct VisibleGadgetLists *vg = &visible_gadget_lists;
USHORT count;
/* Now check if any visible gadget list exists */
ObtainSemaphore(&vg->vg_Semaphore);
if (count = vg->vg_Count) {
struct GadgetList *gl = (struct GadgetList *)
vg->vg_MinList.mlh_Head;
USHORT i;
BOOL found = FALSE;
/* Search all gadget lists displayed on given window */
for (i = 0; i < count && found == FALSE; i++) {
if (gl->gl_Window == win) {
USHORT j, data_entries = gl->gl_DataEntries;
/* Search gadget with given hotkey */
for (j = 0; j < data_entries && found == FALSE; j++) {
struct ExtendedGadget *egad = gl->gl_Gadgets[j];
if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOTKEY &&
egad->eg_Hotkey == hotkey) {
result_egad = egad;
found = TRUE;
}
}
}
gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
}
}
ReleaseSemaphore(&vg->vg_Semaphore);
}
return(result_egad);
}
/* Remove visible gadget lists from given window */
USHORT
remove_visible_gadget_lists(struct Window *win, struct MinList *list)
{
struct GadgetList *gl;
USHORT count = 0;
NewList((struct List *)list);
while (gl = get_first_gadget_list(win)) {
remove_gadgets(gl);
AddHead((struct List *)list, (struct Node *)&gl->gl_MinNode);
count++;
}
return(count);
}
/* Find first visible gadget list for given window */
STATIC struct GadgetList *
get_first_gadget_list(struct Window *win)
{
struct VisibleGadgetLists *vg = &visible_gadget_lists;
struct GadgetList *gl, *gl_return = NULL;
ObtainSemaphore(&vg->vg_Semaphore);
gl = (struct GadgetList *)&vg->vg_MinList.mlh_Head;
while (gl->gl_MinNode.mln_Succ) {
if (gl->gl_Window == win) {
gl_return = gl;
break;
}
gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
}
ReleaseSemaphore(&vg->vg_Semaphore);
return(gl_return);
}
/* Display visible gadget lists on given window */
VOID
display_visible_gadget_lists(struct Window *win, struct MinList *list)
{
struct GadgetList *gl;
while (gl = (struct GadgetList *)RemHead((struct List *)list)) {
display_gadgets(win, gl);
}
}
/* Convert given RAWKEY IntuiMessage to ASCII */
UBYTE
convert_rawkey_to_ascii(struct IntuiMessage *im)
{
UBYTE key = 0;
/* First check for RAWKEY event */
if (im->Class == RAWKEY) {
struct InputEvent input_event, *ie = &input_event;
BYTE buffer[CONVERT_BUFFER_SIZE];
/* Build InputEvent for console device */
ie->ie_NextEvent = NULL;
ie->ie_Class = IECLASS_RAWKEY;
ie->ie_SubClass = IECLASS_NULL;
ie->ie_Code = im->Code;
ie->ie_Qualifier = im->Qualifier;
ie->ie_EventAddress = *((APTR *)im->IAddress);
/* Convert it and check number of returned keys */
if (RawKeyConvert(ie, &buffer[0], CONVERT_BUFFER_SIZE, NULL) == 1) {
key = (UBYTE)buffer[0];
}
}
return(key);
}